import 'package:image/image.dart' as img;
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/services.dart' show rootBundle;

import 'package:signage/app/modules/template/edit_template/controllers/edit_template_controller.dart';
import 'package:signage/utils/eink_image_processor.dart';

abstract class BoardElement {
  String id;
  Rx<Offset> position;
  Rx<Size> size;
  ElementType type;
  EditTemplateController? controller;

  BoardElement({
    required this.id,
    required Offset initialPosition,
    required Size initialSize,
    required this.type,
  })  : position = initialPosition.obs,
        size = initialSize.obs {
    controller = Get.isRegistered<EditTemplateController>()
        ? Get.find<EditTemplateController>()
        : null;
  }

  Widget buildWidget() {
    return Obx(() {
      return Stack(
        children: [
          buildContent(),
          Container(
            width: size.value.width,
            height: size.value.height,
            decoration: BoxDecoration(
              border: Border.all(
                color: controller?.showBorders.value == true &&
                        controller?.selectedElement.value?.id == id
                    ? const Color.fromARGB(255, 124, 91, 30)
                    : Colors.transparent,
                width: 1.h,
              ),
            ),
          ),
        ],
      );
    });
  }

  Widget buildContent();
}

class TextBoardElement extends BoardElement {
  RxString text;
  Rx<double> fontSize;
  Rx<Color> color;
  Rx<FontWeight> fontWeight;
  Rx<TextAlign> textAlign;
  Rx<bool> isItalic;
  Rx<bool> isUnderline;
  RxString fontFamily; // 添加这一行
  Rx<bool> isScalable;
  Rx<bool> isLocked;
  late final TextEditingController textController;

  @override
  String toString() {
    return 'TextBoardElement: {'
        'id: $id, '
        'position: ${position.value.dx}, ${position.value.dy}, '
        'size: ${size.value.width}, ${size.value.height}, '
        'type: $type, '
        'text: ${text.value}, '
        'fontSize: ${fontSize.value}, '
        'color: ${color.value}, '
        'fontWeight: ${fontWeight.value}, '
        'textAlign: ${textAlign.value}, '
        'isItalic: ${isItalic.value}, '
        'isUnderline: ${isUnderline.value}, '
        'fontFamily: ${fontFamily.value}, '
        'isScalable: ${isScalable.value}, '
        'isLocked: ${isLocked.value}'
        '}';
  }

  TextBoardElement({
    required String id,
    required Offset initialPosition,
    required Size initialSize,
    required String initialText,
    double initialFontSize = 16,
    Color initialColor = Colors.black,
    FontWeight initialFontWeight = FontWeight.normal,
    TextAlign initialTextAlign = TextAlign.left,
    String initialFontFamily = 'Arial',
    bool initialIsItalic = false,
    bool initialIsUnderline = false,
    bool initialIsScalable = true,
    bool initialIsLocked = false,
  })  : text = initialText.obs,
        fontSize = initialFontSize.obs,
        color = initialColor.obs,
        fontWeight = initialFontWeight.obs,
        textAlign = initialTextAlign.obs,
        isItalic = initialIsItalic.obs,
        isUnderline = initialIsUnderline.obs,
        isScalable = initialIsScalable.obs,
        isLocked = initialIsLocked.obs,
        fontFamily = RxString(initialFontFamily),
        super(
          id: id,
          initialPosition: initialPosition,
          initialSize: initialSize,
          type: ElementType.text,
        ) {
    textController = TextEditingController(text: initialText);
    textController.addListener(() {
      if (text.value != textController.text) {
        text.value = textController.text;
        updateTextSize();
      }
    });

    WidgetsBinding.instance.addPostFrameCallback((_) {
      updateTextSize();
    });
  }

  void updateTextSize() {
    final textPainter = TextPainter(
      text: TextSpan(
        text: text.value,
        style: TextStyle(
          fontSize: fontSize.value,
          color: color.value,
          fontWeight: fontWeight.value,
          fontFamily: fontFamily.value,
          fontStyle: isItalic.value ? FontStyle.italic : FontStyle.normal,
          decoration: isUnderline.value
              ? TextDecoration.underline
              : TextDecoration.none,
        ),
      ),
      textDirection: TextDirection.ltr,
      textAlign: textAlign.value,
    )..layout();

    // 强制布局两次以获得更准确的测量结果
    textPainter.layout(maxWidth: double.infinity);
    textPainter.layout();

    // 根据文本内容动态调整padding
    // 检查是否包含中文字符
    RegExp(r'[\u4e00-\u9fa5]').hasMatch(text.value);
    // 中文使用较大的padding，英文使用较小的padding
    size.value = Size(textPainter.width, textPainter.height); // 中文时适当增加高度
    print('size: ${size.value}');
  }

  void dispose() {
    textController.dispose();
  }

  @override
  Widget buildContent() {
    return Text(
      text.value,
      textAlign: textAlign.value,
      maxLines: 1,
      style: TextStyle(
        fontSize: fontSize.value,
        color: color.value,
        fontWeight: fontWeight.value,
        fontFamily: fontFamily.value,
        fontStyle: isItalic.value ? FontStyle.italic : FontStyle.normal,
        decoration:
            isUnderline.value ? TextDecoration.underline : TextDecoration.none,
      ),
    );
  }
}

class ImageBoardElement extends BoardElement {
  final imagePath = Rx<String>('');
  final initialImagePath = Rx<String>('');
  final processMode = ProcessMode.bwLevel.obs;
  final isFit = false.obs;
  ImageBoardElement({
    required super.id,
    required super.initialPosition,
    required super.initialSize,
  }) : super(
          type: ElementType.image,
        );

  @override
  Widget buildContent() {
    return Obx(() {
      return imagePath.value.startsWith('assets/')
          ? Image.asset(
              imagePath.value,
              width: size.value.width,
              height: size.value.height,
              fit: isFit.value ? BoxFit.fill : BoxFit.contain,
            )
          : Image.file(
              File(imagePath.value),
              width: size.value.width,
              height: size.value.height,
              fit: isFit.value ? BoxFit.fill : BoxFit.contain,
            );
    });
  }

  @override
  String toString() {
    return 'ImageBoardElement(id: $id, position: ${position.value.dx}, ${position.value.dy}, size: ${size.value.width}, ${size.value.height}, imagePath: $imagePath)';
  }
}

class ColorBlockBoardElement extends BoardElement {
  Rx<Color> color;

  ColorBlockBoardElement({
    required String id,
    required Offset initialPosition,
    required Size initialSize,
    required Color initialColor,
  })  : color = initialColor.obs,
        super(
          id: id,
          initialPosition: initialPosition,
          initialSize: initialSize,
          type: ElementType.colorBlock,
        );

  @override
  Widget buildContent() {
    return Container(
      width: size.value.width,
      height: size.value.height,
      color: color.value,
    );
  }

  @override
  String toString() {
    return 'ColorBlockBoardElement(id: $id, position: ${position.value.dx}, ${position.value.dy}, size: ${size.value.width}, ${size.value.height}, color: $color)';
  }
}

enum ElementType { text, image, colorBlock, background }

class BackgroundBoardElement extends BoardElement {
  Rx<Color> backgroundColor;
  final processMode = ProcessMode.bwLevel.obs;
  final backgroundImagePath = Rx<String>('');
  final initialBackgroundImagePath = Rx<String>('');
  final _lastImageHash = ''.obs;

  BackgroundBoardElement({
    required String id,
    required Offset initialPosition,
    required Size initialSize,
    Color initialColor = Colors.white,
  })  : backgroundColor = initialColor.obs,
        super(
          id: id,
          initialPosition: initialPosition,
          initialSize: initialSize,
          type: ElementType.background,
        );

  @override
  Widget buildContent() {
    return Obx(() {
      if (backgroundImagePath.value.isEmpty) {
        return Container(
          width: size.value.width,
          height: size.value.height,
          color: backgroundColor.value,
        );
      }

      String currentHash = backgroundImagePath.value;
      if (currentHash != _lastImageHash.value) {
        print('Background image changed!');
        _lastImageHash.value = currentHash;
      }

      return backgroundImagePath.value.startsWith('assets/')
          ? Image.asset(
              backgroundImagePath.value,
              key: ValueKey(_lastImageHash.value),
              width: size.value.width,
              height: size.value.height,
              fit: BoxFit.cover,
            )
          : Image.file(
              File(backgroundImagePath.value),
              key: ValueKey(_lastImageHash.value),
              width: size.value.width,
              height: size.value.height,
              fit: BoxFit.cover,
              gaplessPlayback: false,
            );
    });
  }

  @override
  String toString() {
    return 'BackgroundBoardElement(id: $id, position: ${position.value.dx}, ${position.value.dy}, size: ${size.value.width}, ${size.value.height}, backgroundColor: ${backgroundColor.value})';
  }
}
